<html lang="en-US">

<head>
    
<title>Proto 代码到底放哪里？ - 花落雨忧</title>

<meta property="og:title" content="Proto 代码到底放哪里？ - 花落雨忧">



    



    
    <meta property="description" content="虽然公司已经从大单体切换为微服务化有一定的年头了，但一些细节方面的处理总会有不同的人有不同的看法，这其中一个讨论点，就是 Proto 这个 IDL 的代码到底放在哪里？
目前来看，一共有如下方案， 我们一起来探讨一下 Proto 的存储方式和对应带来的优缺点。
[&amp;hellip;] 直接将项目所依赖到的所有 Proto 文件都存放在 proto/ 目录下，不经过开发工具的自动拉取和发布： &amp;hellip;">
    <meta property="og:description" content="虽然公司已经从大单体切换为微服务化有一定的年头了，但一些细节方面的处理总会有不同的人有不同的看法，这其中一个讨论点，就是 Proto 这个 IDL 的代码到底放在哪里？
目前来看，一共有如下方案， 我们一起来探讨一下 Proto 的存储方式和对应带来的优缺点。
[&amp;hellip;] 直接将项目所依赖到的所有 Proto 文件都存放在 proto/ 目录下，不经过开发工具的自动拉取和发布： &amp;hellip;">
    






<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="viewport" content="width=device-width,initial-scale=1">

<link rel="shortcut icon" href="https://www.lican.site/logo/logo.png" type="image/x-icon" />



<link rel="stylesheet" href="/css/style.min.css" />

<link rel="stylesheet" href="/css/reset.min.css" />




<script src="https://www.lican.site/js/highlight.min.js"></script>

<script>
hljs.configure({ ignoreUnescapedHTML: true })
hljs.highlightAll();
</script>


<script src="https://www.lican.site/js/jquery.min.js"></script>




<link href="https://www.lican.site/css/hugo-code.min.css" rel="stylesheet" />



    <style>
        .post-content img {
            max-width: 400px;
        }
    </style>
</head>

<body id="period" class="home blog">
    <a class="skip-content" href="#main">Press "Enter" to skip to content</a>
    <div id="overflow-container" class="overflow-container">
        <header class="site-header" id="site-header" role="banner">
    <div class="max-width">
        <div id="title-container" class="title-container">
            <div id="site-title" class="site-title"><a href="/">花落雨忧</a></div>
            <p class="tagline">思所及 力所行 方为真.</p>
        </div>
        
        <div id="menu-primary-container" class="menu-primary-container">
            <div class="icon-container">
            </div>
            <div id="menu-primary" class="menu-container menu-primary" role="navigation">
                <nav class="menu">
                    <ul id="menu-primary-items" class="menu-primary-items">
                        
                        
                        <li id="menu-item-0"
                            class="menu-item menu-item-type-custom menu-item-object-custom ">
                            <a href="/posts" aria-current="page" tabindex="0">首页</a></li>
                        
                        <li id="menu-item-1"
                            class="menu-item menu-item-type-custom menu-item-object-custom ">
                            <a href="/tech/" aria-current="page" tabindex="1">技术文档</a></li>
                        
                        <li id="menu-item-2"
                            class="menu-item menu-item-type-custom menu-item-object-custom ">
                            <a href="/article/" aria-current="page" tabindex="2">文章</a></li>
                        
                        <li id="menu-item-3"
                            class="menu-item menu-item-type-custom menu-item-object-custom ">
                            <a href="/project/" aria-current="page" tabindex="3">项目</a></li>
                        
                        <li id="menu-item-4"
                            class="menu-item menu-item-type-custom menu-item-object-custom ">
                            <a href="/about/" aria-current="page" tabindex="4">关于</a></li>
                        
                    </ul>
                </nav>
            </div>
        </div>
    </div>
</header>
        <div id="primary-container" class="primary-container">
            <div class="max-width">
                <section id="main" class="main" role="main">
                    <div id="loop-container" class="loop-container">
                        <div
                            class="post type-post status-publish format-standard hentry entry">
                            <article>
                                <div class="post-container">
                                    <div class="post-header">
                                        <h2 class="post-title">
                                            <a href="/posts/where-is-proto/">Proto 代码到底放哪里？</a>
                                        </h2>
                                        
                                        <div class="post-byline">Published on
                                            <a class="date" href="javascript:;">2020/05/23</a>
                                            
                                            
                                            
                                            
                                            
                                        
                                    </div>
                                    <div class="post-content">
                                        <p>虽然公司已经从大单体切换为微服务化有一定的年头了，但一些细节方面的处理总会有不同的人有不同的看法，这其中一个讨论点，就是 Proto 这个 IDL 的代码到底放在哪里？</p>
<p>目前来看，一共有如下方案， 我们一起来探讨一下 Proto 的存储方式和对应带来的优缺点。</p>
<h2 id="方案一存放在代码仓库">方案一：存放在代码仓库</h2>
<p>直接将项目所依赖到的所有 Proto 文件都存放在 <code>proto/</code> 目录下，不经过开发工具的自动拉取和发布：</p>
<p><img src="https://image.eddycjy.com/7e95a76d548197cf73e7238ee5df27e6.jpg" alt="image"></p>
<h3 id="缺点">缺点</h3>
<ol>
<li>
<p>项目所有依赖的 Proto 都存储在代码仓库下，因此所有依赖 Proto 都需要人工的向其它业务组 “要” 来，再放到 <code>proto/</code> 目录下，人工介入极度麻烦。</p>
</li>
<li>
<p>Proto 升级和变更，经常要重复第一步，沟通成本高。</p>
</li>
</ol>
<h3 id="优点">优点</h3>
<ol>
<li>
<p>项目所有依赖的 Proto 都存储在代码仓库下，因此不涉及个人开仓库权限的问题。</p>
</li>
<li>
<p>多 Proto 的切换开销减少，因为都在代码仓库下，不需要看这看那。</p>
</li>
</ol>
<h2 id="方案二独立仓库">方案二：独立仓库</h2>
<p>独立仓库存储是我们最早采取的方式，也就是每个服务对应配套一个 Proto 仓库：</p>
<p><img src="https://image.eddycjy.com/a7575628ff1ae9179f022d477aba9df1.png" alt="image"></p>
<p>这个方案的好处就是可以独立管理所有 Proto 仓库，并且权限划分清晰。但最大的优点也是最大的缺点，因为一个服务会依赖多个 Proto 仓库，并且存在跨业务组调用的情况：</p>
<p><img src="https://image.eddycjy.com/31c5a5b5652f44750124c15e1c0ef397.jpg" alt="image"></p>
<p>如上图所示，svc-user 服务分别依赖了三块 Proto 仓库，分别是自己组的、业务组 A、业务组 B 总共的 6 个 Proto 仓库。</p>
<h3 id="缺点-1">缺点</h3>
<ol>
<li>假设你是一个新入职的开发人员，那么你就需要找不同的业务组申请不同的仓库权限，非常麻烦。如果没有批量赋权工具，也没有管理者权限，那么就需要一个个赋权，非常麻烦。</li>
<li>在运行服务的时候，你需要将所有相关联的 Proto 仓库拉取下来，如果没有工具做半自动化的支持，麻烦程度无法忍受。</li>
</ol>
<h3 id="优点-1">优点</h3>
<ol>
<li>
<p>使得安全性较高（但 IDL 本身没有太多的秘密）。</p>
</li>
<li>
<p>按需拉取，不需要关注其余的服务 Proto。</p>
</li>
</ol>
<h2 id="方案三集中仓库">方案三：集中仓库</h2>
<p>集中仓库也是一些公司考虑的方式之一，是按公司或大事业部的维度进行 Proto 代码的存储，这样子只需要拉取一个仓库，就可以获取到所有所需的 IDL：</p>
<p><img src="https://image.eddycjy.com/9f0c7821aa2d42857685e04d9df25740.jpg" alt="image"></p>
<h3 id="缺点-2">缺点</h3>
<ol>
<li>
<p>安全性下降，因为其它业务组的 IDL 也全都 “泄露” 了。</p>
</li>
<li>
<p>非按需拉取，在查看原始文件时，需要关注一些多余的。</p>
</li>
</ol>
<h3 id="优点-2">优点</h3>
<ol>
<li>
<p>只需要拉取一次 Proto 仓库就可以轻松把一个服务所需的 IDL 集齐。</p>
</li>
<li>
<p>仓库权限管理的复杂度下降。</p>
</li>
</ol>
<h2 id="方案四镜像仓库">方案四：镜像仓库</h2>
<p>结合上面几种方案的特点，我们也可以得出镜像仓库的方式，也就是自己服务的 Proto 文件存放在代码仓库的 proto 文件中，在本次 feature 提交或发布后，自动同步到镜像仓库去。</p>
<p>而你所依赖的其他服务 Proto 则直接通过读取集中的镜像仓库的方式获取：</p>
<p><img src="https://image.eddycjy.com/d90a0040923aacced41549ea902e6cde.jpg" alt="image"></p>
<p>这样子的话，通过开发工具的配合，开发人员在开发时就只需要关注自己项目的 Proto，集中的镜像仓库用于构建和部署时就可以了，大幅度降低了多 Proto 的关注和切换开销。</p>
<h2 id="方案五其他">方案五：其他</h2>
<p>本质上上述的所有方案多多少少都有一些利弊存在，并且都需要开发工具来进行支持，否则实操起来还是非常麻烦。</p>
<p>如果想一劳永逸，可以通过云开发环境来解决，因为在分配云开发机时，你已经有了身份认证，你能够拥有什么权限，不能拥有什么权限，基本都是明确的，并且一般在组内、跨组联调时，也可以直接调度，不需要像其它方案那样进行过多的关注，甚至在自己本地运行一套微服务。</p>
<p>但这需要大量的工具/资源支持。</p>
<h2 id="小结">小结</h2>
<p>在本文中我介绍了比较常见的 5 种 Proto 代码的管理方式，其各有利弊，不同公司不同人的理解或适配度都不一样，大家可以根据实际环境进行选用，并且建议拉上核心的人员进行讨论和选型，因为 Proto 代码涉略面还是比较广的，多多少少都有人有不一样的看法。</p>


                                        
                                        
                                        
                                        
                                    </div>

                                    
                                    
                                    

                                    
                                    <div class="post-meta">
                                        
                                        
                                        <div class="post-tags">
                                            <ul>
                                            
                                            <li>
                                                <a href="/tags/protobuf" title="View all posts tagged match">protobuf</a>
                                            </li>
                                            
                                            </ul>
                                        </div>
                                        
                                        
                                        <nav class="further-reading">
                                            
                                            <div class="previous">
                                                <span>&lt;&lt; Prev</span>
                                                <a href="https://www.lican.site/posts/prometheus/2020-05-16-pull/"
                                                    rel="prev">使用 Prometheus 对 Go 程序进行指标采集</a> </div>
                                            
                                            
                                            <div class="next">
                                                <span>Next >></span>
                                                <a href="https://www.lican.site/posts/why-container-memory-exceed/">为什么容器内存占用居高不下，频频 OOM</a> 
                                            </div>
                                            
                                        </nav>
                                    </div>
                                    
                                    

                                    
                                    
                                    

                                </div>
                            </article>
                        </div>
                    </div>
                </section>
                <aside class="sidebar sidebar-primary" id="sidebar-primary" role="complementary">
    <h1 class="screen-reader-text">Sidebar</h1>
    

    
    
    <section id="text-2" class="widget widget_text">
        <div class="textwidget">
            
            <div id="profile">
                <div id="profile_picture"><img src="https://www.lican.site/logo/logo.png"></div>
                <div id="profile_intro">
                    <p><span class="name">Lican</span></p>
                    <p class="intro">全栈开发者，爱好造轮子。</p>
                </div>
            </div>
            
            <p>
                <script type="text/javascript">
                    (function ($) {
                        $(document).ready(function () {
                            var menuPrimaryContainer = $('#menu-primary-container');
                            var profile = $('#text-2');
                            $('#toggle-navigation').click(function () {
                                if (menuPrimaryContainer.hasClass('open')) {
                                    profile.removeClass('open');
                                } else {
                                    profile.addClass('open');
                                }
                            });
                        });
                    })(jQuery);
                </script>
            </p>
        </div>
    </section>
    
    
    
    
    
    <section id="text-5" class="widget widget_text">
        <h2 class="widget-title">开源项目</h2>
        <div class="textwidget">
            <div id="projects" style="line-height: 22px;">
                
                <a href="https://github.com/idoubi/gonews"
                    target="_blank">gonews</a>: &nbsp;Daily news for golang<br>
                
                <a href="https://github.com/idoubi/sql2struct"
                    target="_blank">sql2struct</a>: &nbsp;Generate go struct according to SQL<br>
                
                <a href="https://github.com/idoubi/goz"
                    target="_blank">goz</a>: &nbsp;Request library used in golang<br>
                
        </div>
    </section>
    
    

    
    
    
    
    

    
    
    

    
    
    

    
    
    
    
</aside>
            </div>
        </div>

        <footer id="site-footer" class="site-footer" role="contentinfo">
    <div class="max-width">
    </div>
    <div class="footer">
        <div id="footercontent">
            © lican.vip All rights reserved<br/>
            Built with Hugo Theme <a href="https://github.com/idoubi/hugo-theme-period" target="_blank">Period</a>
        </div>
    </div>
</footer>

<script>
    var _hmt = _hmt || [];
    (function() {
      var hm = document.createElement("script");
      hm.src = "https://hm.baidu.com/hm.js?e8351b6d4626d5881d439ea1f6184baa";
      var s = document.getElementsByTagName("script")[0]; 
      s.parentNode.insertBefore(hm, s);
    })();
</script>
    
    
    </div>
    
</body>

</html>